#ifndef GAME_TIMER_H_
#include "../Core/GameTimer.h"
#endif

#include <Windows.h>

GameTimer::GameTimer()
	: m_dSecondsPerCount( 0.0 )
	, m_dDeltaTime( -1.0 )
	, m_i64BaseTime( 0 )
	, m_i64PauseTime( 0 )
	, m_i64StopTime( 0 )
	, m_i64PrevTime( 0 )
	, m_i64CurrTime( 0 )
	, m_bStopped( false )
{
	__int64 i64CountsPerSec;
	QueryPerformanceFrequency( (LARGE_INTEGER*)&i64CountsPerSec );

	m_dSecondsPerCount = 1.0 / (double)i64CountsPerSec;
}

GameTimer::~GameTimer()
{

}

/*
	* GetGameTimer.

	* Returns the total time elapsed since reset() was called.
	* NOTE : This function does NOT count the time when the clock is stopped. 
*/
float GameTimer::GetGameTime( void ) const
{
	/*	
		If we are stopped then do not count the time that has passed since stopped. 

		 ----*---------------*------------------------------*------> time
		m_i64BaseTime       m_i64StopTime                      m_64CurrTime
	*/
	if( m_bStopped )
	{
		return (float)( (m_i64StopTime - m_i64BaseTime) * m_dSecondsPerCount );
	}

	/* 
		The distancem_i64CurrTime - m_i64BaseTime includes pause time, 
		which we do not want to count. To correct this, we can subtract the
		pause time from m_i64CurrTime

		 (mi64CurrTime - mi64PausedTime) - mi64BaseTime 
		
		                    |<-------d------->|
		 ----*---------------*-----------------*------------*------> time
		 mBaseTime       mStopTime        startTime     mCurrTime

	*/
	else
	{
		return (float)( ((m_i64CurrTime - m_i64PauseTime) - m_i64BaseTime) * m_dSecondsPerCount );
	}
}

/*
	* GetDeltaTime
	* Get time between the current and the last frame in seconds.
*/
float GameTimer::GetDeltaTime( void ) const
{
	return (float)m_dDeltaTime;
}

/* 
	* Reset.
	* Call only once before the message loop to reset the timer.
*/
void GameTimer::Reset( void )
{
	__int64 i64CurrTime;
	QueryPerformanceCounter( (LARGE_INTEGER*)i64CurrTime );

	m_i64BaseTime = i64CurrTime;
	m_i64PrevTime = i64CurrTime;
	m_i64StopTime = 0;
	m_bStopped = false;
}

/*
	* Start
	* When the timer is unpaused.
*/
void GameTimer::Start( void )
{
	__int64 i64StartTime;
	QueryPerformanceCounter( (LARGE_INTEGER*)&i64StartTime );

	/*	
		* Accumulate the time elapsed between the stop and start pointers.
		                    |<-------d------->|
		----*---------------*-----------------*------------> time
		  mBaseTime       mStopTime        startTime  
	*/
	if( m_bStopped )
	{
		m_i64PauseTime = (i64StartTime - m_i64StopTime);

		m_i64PrevTime = i64StartTime;
		m_bStopped = false;
		m_i64StopTime = 0;
	}
}

/* 
	* Stop
	* When the timer is stopped/paused.
*/
void GameTimer::Stop( void )
{
	if( !m_bStopped )
	{
		__int64 i64CurrTime;
		QueryPerformanceCounter( (LARGE_INTEGER*)&i64CurrTime );

		m_i64StopTime = i64CurrTime;
		m_bStopped = false;
	}
}

/* 
	* Tick
	* Tick to get every frame that has passed.
*/
void GameTimer::Tick( void )
{
	if( m_bStopped )
	{
		m_dDeltaTime = 0.0;
		return;
	}

	__int64 i64CurrTime;
	QueryPerformanceCounter( (LARGE_INTEGER*)&i64CurrTime );

	m_i64CurrTime = i64CurrTime;

	/* Time difference between this frame and the current frame. */
	m_dDeltaTime = ( m_i64CurrTime - m_i64PrevTime ) * m_dSecondsPerCount;

	/* Prepare for next frame. */
	m_i64PrevTime = m_i64CurrTime;

	if( 0.0 < m_dDeltaTime )
	{
		m_dDeltaTime = 0.0;
	}
}











